﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Sokoban.ViewModel.Boxes;

namespace Sokoban.Model
{
    public static class MapReader
    {
        //public static Map ReadMap(string path)
        //{
        //    Exception excMap = new Exception("Map is invalid!");
        //    Exception excTile = new Exception("Map is invalid at tiles!");
        //    int x = 0, y = 0, currentX = 0, currentY = 0;
        //    Map map = new Map("",0,0);
        //    XmlReader reader = XmlReader.Create(path);
        //    reader.Read();
        //    if (reader.Name == "xml")
        //    {
        //        reader.Read();
        //        reader.Read();
        //    }
        //    if (reader.Name == "map")
        //    {
        //        while (reader.Read())
        //        {
        //            if (reader.IsStartElement())
        //            {
        //                switch (reader.Name)
        //                {
        //                    case "name":
        //                        {
        //                            map.Name = reader.GetAttribute("val");
        //                            break;
        //                        }
        //                    case "x":
        //                        {
        //                            x = int.Parse(reader.GetAttribute("val"));
        //                            break;
        //                        }
        //                    case "y":
        //                        {
        //                            y = int.Parse(reader.GetAttribute("val"));
        //                            break;
        //                        }
        //                    case "tiles":
        //                        {
        //                            if (map.GridMatrix != null)
        //                            {
        //                                throw excMap;
        //                            }
        //                            map.GridMatrix = new AbstractBox[y, x];
        //                            for (int i = 0; i < y; i++)
        //                            {
        //                                for (int j = 0; j < x; j++)
        //                                {
        //                                    reader.Read();
        //                                    reader.Read();
        //                                    if (reader.Name != "tile")
        //                                    {
        //                                        throw excTile;
        //                                    }

        //                                    reader.Read();
        //                                    reader.Read();
        //                                    if (reader.Name != "x")
        //                                    {
        //                                        throw excTile;
        //                                    }
        //                                    currentX = int.Parse(reader.GetAttribute("pos"));

        //                                    reader.Read();
        //                                    reader.Read();
        //                                    if (reader.Name != "y")
        //                                    {
        //                                        throw excTile;
        //                                    }
        //                                    currentY = int.Parse(reader.GetAttribute("pos"));

        //                                    reader.Read();
        //                                    reader.Read();
        //                                    if (reader.Name == "type")
        //                                    {
        //                                        switch (reader.GetAttribute("val"))
        //                                        {
        //                                            case "box":
        //                                                {
        //                                                    map.GridMatrix[j, i] = new Box(currentX, currentY);
        //                                                    break;
        //                                                }
        //                                            case "empty":
        //                                                {
        //                                                    map.GridMatrix[j, i] = new Empty(currentX, currentY);
        //                                                    break;
        //                                                }
        //                                            case "goal":
        //                                                {
        //                                                    map.GridMatrix[j, i] = new Goal(currentX, currentY);
        //                                                    break;
        //                                                }
        //                                            case "player":
        //                                                {
        //                                                    map.GridMatrix[j, i] = new Player(currentX, currentY);
        //                                                    break;
        //                                                }
        //                                            case "wall":
        //                                                {
        //                                                    map.GridMatrix[j, i] = new Wall(currentX, currentY);
        //                                                    break;
        //                                                }
        //                                            default:
        //                                                throw excTile;
        //                                        }


        //                                    }
        //                                    else throw excTile;

        //                                    reader.Read();
        //                                    reader.Read();
        //                                }
        //                            }
        //                            reader.Read();
        //                            reader.Read();
        //                            break;
        //                        }
        //                    default:
        //                        throw excMap;
        //                }
        //            }
        //        }
        //    }

        //    return map;
        //}

        public static Map ReadMap(string path)
        {
            Exception excMap = new Exception("Map is invalid!");
            Exception excTile = new Exception("Map is invalid at tiles!");
            int x = 0, y = 0, currentX = 0, currentY = 0;
            Map map = new Map();
            XmlReader reader = XmlReader.Create(path);
            reader.Read();
            if (reader.Name == "xml")
            {
                reader.Read();
                if (reader.Name == "")
                {
                    reader.Read();
                }
            }
            if (reader.Name == "map")
            {
                while (reader.Read())
                {
                    if (reader.IsStartElement())
                    {
                        switch (reader.Name)
                        {
                            case "name":
                                {
                                    map.Name = reader.GetAttribute("val");
                                    break;
                                }
                            case "x":
                                {
                                    x = int.Parse(reader.GetAttribute("val"));
                                    break;
                                }
                            case "y":
                                {
                                    y = int.Parse(reader.GetAttribute("val"));
                                    break;
                                }
                            case "tiles":
                                {
                                    if (map.GridMatrix != null)
                                    {
                                        throw excMap;
                                    }
                                    map.GridMatrix = new AbstractBox[y, x];
                                    for (int i = 0; i < y; i++)
                                    {
                                        for (int j = 0; j < x; j++)
                                        {
                                            reader.Read();
                                            if (reader.Name == "")
                                            {
                                                reader.Read();
                                            }
                                            if (reader.Name != "tile")
                                            {
                                                throw excTile;
                                            }

                                            reader.Read();
                                            if (reader.Name == "")
                                            {
                                                reader.Read();
                                            }
                                            if (reader.Name != "x")
                                            {
                                                throw excTile;
                                            }
                                            currentX = int.Parse(reader.GetAttribute("pos"));

                                            reader.Read();
                                            if (reader.Name == "")
                                            {
                                                reader.Read();
                                            }
                                            if (reader.Name != "y")
                                            {
                                                throw excTile;
                                            }
                                            currentY = int.Parse(reader.GetAttribute("pos"));

                                            reader.Read();
                                            if (reader.Name == "")
                                            {
                                                reader.Read();
                                            }
                                            if (reader.Name == "type")
                                            {
                                                switch (reader.GetAttribute("val"))
                                                {
                                                    case "box":
                                                        {
                                                            map.GridMatrix[i, j] = new Box(currentX, currentY);
                                                            break;
                                                        }
                                                    case "empty":
                                                        {
                                                            map.GridMatrix[i, j] = new Empty(currentX, currentY);
                                                            break;
                                                        }
                                                    case "goal":
                                                        {
                                                            map.GridMatrix[i, j] = new Goal(currentX, currentY);
                                                            break;
                                                        }
                                                    case "player":
                                                        {
                                                            map.GridMatrix[i, j] = new Player(currentX, currentY);
                                                            break;
                                                        }
                                                    case "wall":
                                                        {
                                                            map.GridMatrix[i, j] = new Wall(currentX, currentY);
                                                            break;
                                                        }
                                                    default:
                                                        throw excTile;
                                                }


                                            }
                                            else throw excTile;

                                            reader.Read();
                                            if (reader.Name == "")
                                            {
                                                reader.Read();
                                            }
                                        }
                                    }
                                    reader.Read();
                                    if (reader.Name == "")
                                    {
                                        reader.Read();
                                    }
                                    break;
                                }
                            default:
                                throw excMap;
                        }
                    }
                }
            }

            return map;
        }
    }
}
